package com.engine4cloud.tdf.supervision.service.impl;

import com.engine4cloud.tdf.admin.api.dto.AreaDepartQueryDTO;
import com.engine4cloud.tdf.admin.api.entity.SysDept;
import com.engine4cloud.tdf.admin.api.feign.RemoteDeptService;
import com.engine4cloud.tdf.common.core.constant.SecurityConstants;
import com.engine4cloud.tdf.common.core.constant.enums.*;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.R;
import com.engine4cloud.tdf.common.core.util.RetOps;
import com.engine4cloud.tdf.supervision.component.CallBackComponent;
import com.engine4cloud.tdf.supervision.convert.JzdxReleaseConvert;
import com.engine4cloud.tdf.supervision.dto.SpAuditDTO;
import com.engine4cloud.tdf.supervision.dto.create.SpAuditResultCreateDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.SpChangePlaceResult;
import com.engine4cloud.tdf.supervision.dto.update.JzdxAuditDepartUpdateDTO;
import com.engine4cloud.tdf.supervision.dto.update.JzdxUpdateStatusDTO;
import com.engine4cloud.tdf.supervision.dto.update.SpNormalPreActionUpdateDTO;
import com.engine4cloud.tdf.supervision.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

@Service
@Slf4j
public class SpChangePlaceAuditServiceImpl implements SpChangePlaceAuditService {
    @Resource
    private SpAuditService auditService;
    @Resource
    private SpAuthorizeService authorizeService;
    @Resource
    private SpChangePlaceService changePlaceService;
    @Resource
    private JzdxService jzdxService;
    @Resource
    private JzdxAuditResultService auditResultService;
    @Resource
    private JzdxReleaseService releaseService;
    @Lazy
    @Resource
    private JzdxElectronicFenceService electronicFenceService;
    @Resource
    private RemoteDeptService remoteDeptService;
    @Resource
    private CallBackComponent callBackComponent;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(SpAuditDTO dto) {
        SpChangePlaceResult old = Optional.ofNullable(changePlaceService.getByBatch(dto.getLcbh()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        changePlaceService.changeAction(new SpNormalPreActionUpdateDTO(dto.getRybh(), dto.getLcbh(), NormalAuditActionStatusEnum.VILLAGE_AUDIT));
        return auditService.villageAudit(new SpAuditResultCreateDTO(dto, AuditBusinessTypeEnum.CHANGE_PLACE, AllAuditActionStatusEnum.VILLAGE_AUDIT));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refuse(SpAuditDTO dto) {
        SpChangePlaceResult old = Optional.ofNullable(changePlaceService.getByBatch(dto.getLcbh()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));
        changePlaceService.changeAction(new SpNormalPreActionUpdateDTO(dto.getRybh(), dto.getLcbh(), NormalAuditActionStatusEnum.REFUSE));
        return auditService.refuse(new SpAuditResultCreateDTO(dto, AuditBusinessTypeEnum.CHANGE_PLACE, AllAuditActionStatusEnum.REFUSE));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean authorize(SpAuditDTO dto) {
        JzdxResultDTO dx = Optional.ofNullable(jzdxService.getByCode(dto.getRybh()))
                .orElseThrow(() -> new ValidateCodeException("矫正对象不存在"));

        SpChangePlaceResult old = Optional.ofNullable(changePlaceService.getByBatch(dto.getLcbh()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        //审核流程
        changePlaceService.changeAction(new SpNormalPreActionUpdateDTO(dto.getRybh(), dto.getLcbh(), NormalAuditActionStatusEnum.AUTHORIZE));
        authorizeService.authorize(new SpAuditResultCreateDTO(dto, AuditBusinessTypeEnum.CHANGE_PLACE, AllAuditActionStatusEnum.AUTHORIZE));

        //省内，转移部门，变成待接收
        if (Objects.equals(ChangePlaceTypeEnum.IN_PROVINCE.getType(), old.getBglx())) {
            //获取迁入地区县编码
            R<SysDept> deptRemote = remoteDeptService.geDetailByOrgCode(new AreaDepartQueryDTO(old.getDestinationList().get(2), "3"), SecurityConstants.FROM_IN);
            SysDept dept = RetOps.of(deptRemote).getData()
                    .orElseThrow(() -> new ValidateCodeException("迁入目的地区县没有对应的矫正机构"));

            //转移部门
            jzdxService.changeDepart(new JzdxAuditDepartUpdateDTO(dto.getRybh(), dept.getDeptId()), CorAuditActionStatusEnum.CHANGE_PLACE);
            //设置矫正对象的状态
            auditResultService.setStatus(new JzdxUpdateStatusDTO(dto.getRybh(), dx.getDeptId(), CorAuditActionStatusEnum.CHANGE_PLACE));
            //事务提交之后，解除原电子围栏
            callBackComponent.execute(() -> electronicFenceService.removeBatchByCode(dx.getRybh()));
        } else {
            //省外，解除矫正
            releaseService.create(JzdxReleaseConvert.INSTANCE.changePlaceCreate(dto.getRybh(), "01"));
            //设置矫正对象的状态
            auditResultService.setStatus(new JzdxUpdateStatusDTO(dto.getRybh(), dx.getDeptId(), CorAuditActionStatusEnum.RELEASE));
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean reject(SpAuditDTO dto) {
        SpChangePlaceResult old = Optional.ofNullable(changePlaceService.getByBatch(dto.getLcbh()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));
        changePlaceService.changeAction(new SpNormalPreActionUpdateDTO(dto.getRybh(), dto.getLcbh(), NormalAuditActionStatusEnum.REJECT));
        return authorizeService.reject(new SpAuditResultCreateDTO(dto, AuditBusinessTypeEnum.CHANGE_PLACE, AllAuditActionStatusEnum.REJECT));
    }
}
